/*
===========================================================================

Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.

This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").

Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.

If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.

===========================================================================
*/

#include "Precompiled.h"
#include "globaldata.h"

#include "doomdef.h"
#include "d_event.h"


#include "m_random.h"
#include "p_local.h"
#include "s_sound.h"

// State.
#include "doomstat.h"

// Data.
#include "sounds.h"

#include "p_pspr.h"
#include "d3xp/Game_local.h"

extern bool globalNetworking;



static const float	PISTOL_MAGNITUDE_HIGH			= 0.5f;
static const int	PISTOL_DURATION_HIGH			= 250;
static const float	PISTOL_MAGNITUDE_LOW			= 1.0f;
static const int	PISTOL_DURATION_LOW				= 150;

static const float	SHOTGUN_MAGNITUDE_HIGH			= 0.5f;
static const int	SHOTGUN_DURATION_HIGH			= 250;
static const float	SHOTGUN_MAGNITUDE_LOW			= 1.0f;
static const int	SHOTGUN_DURATION_LOW			= 350;

static const float	CHAINGUN_MAGNITUDE_HIGH			= 0.5f;
static const int	CHAINGUN_DURATION_HIGH			= 250;
static const float	CHAINGUN_MAGNITUDE_LOW			= 1.0f;
static const int	CHAINGUN_DURATION_LOW			= 150;

static const float	PLASMAGUN_MAGNITUDE_HIGH		= 0.5f;
static const int	PLASMAGUN_DURATION_HIGH			= 250;
static const float	PLASMAGUN_MAGNITUDE_LOW			= 1.0f;
static const int	PLASMAGUN_DURATION_LOW			= 150;

static const float	SUPERSHOTGUN_MAGNITUDE_HIGH		= 1.0f;
static const int	SUPERSHOTGUN_DURATION_HIGH		= 250;
static const float	SUPERSHOTGUN_MAGNITUDE_LOW		= 1.0f;
static const int	SUPERSHOTGUN_DURATION_LOW		= 350;

static const float	ROCKET_MAGNITUDE_HIGH			= 1.5f;
static const int	ROCKET_DURATION_HIGH			= 250;
static const float	ROCKET_MAGNITUDE_LOW			= 1.0f;
static const int	ROCKET_DURATION_LOW				= 350;

static const float	BFG_MAGNITUDE_HIGH				= 1.5f;
static const int	BFG_DURATION_HIGH				= 250;
static const float	BFG_MAGNITUDE_LOW				= 1.0f;
static const int	BFG_DURATION_LOW				= 400;


static const float	SAW_IDL_MAGNITUDE_HIGH			= 0.0f;
static const int	SAW_IDL_DURATION_HIGH			= 0;
static const float	SAW_IDL_MAGNITUDE_LOW			= 0.4f;
static const int	SAW_IDL_DURATION_LOW			= 150;

static const float	SAW_ATK_MAGNITUDE_HIGH			= 1.0f;
static const int	SAW_ATK_DURATION_HIGH			= 250;
static const float	SAW_ATK_MAGNITUDE_LOW			= 0.0f;
static const int	SAW_ATK_DURATION_LOW			= 0;

// plasma cells for a bfg attack


//
// P_SetPsprite
//
void
P_SetPsprite
( player_t*	player,
  int		position,
  statenum_t	stnum )
{
	pspdef_t*	psp;
	const state_t*	state;

	psp = &player->psprites[position];

	do
	{
		if( !stnum )
		{
			// object removed itself
			psp->state = NULL;
			break;
		}

		state = &::g->states[stnum];
		psp->state = state;
		psp->tics = state->tics;	// could be 0

		if( state->misc1 )
		{
			// coordinate set
			psp->sx = state->misc1 << FRACBITS;
			psp->sy = state->misc2 << FRACBITS;
		}

		// Call action routine.
		// Modified handling.
		if( state->action )
		{
			state->action( player, psp );
			if( !psp->state )
			{
				break;
			}
		}

		stnum = psp->state->nextstate;

	}
	while( !psp->tics );
	// an initial state of 0 could cycle through
}



//
// P_CalcSwing
//

void P_CalcSwing( player_t*	player )
{
	fixed_t	swing;
	int		angle;

	// OPTIMIZE: tablify this.
	// A LUT would allow for different modes,
	//  and add flexibility.

	swing = player->bob;

	angle = ( FINEANGLES / 70 *::g->leveltime )&FINEMASK;
	::g->swingx = FixedMul( swing, finesine[angle] );

	angle = ( FINEANGLES / 70 *::g->leveltime + FINEANGLES / 2 )&FINEMASK;
	::g->swingy = -FixedMul( ::g->swingx, finesine[angle] );
}



//
// P_BringUpWeapon
// Starts bringing the pending weapon up
// from the bottom of the screen.
// Uses player
//
void P_BringUpWeapon( player_t* player )
{
	statenum_t	newstate;

	if( player->pendingweapon == wp_nochange )
	{
		player->pendingweapon = player->readyweapon;
	}

	if( player->pendingweapon == wp_chainsaw && ( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) ) )
	{
		S_StartSound( player->mo, sfx_sawup );
	}

	newstate = ( statenum_t )( weaponinfo[player->pendingweapon].upstate );

	player->pendingweapon = wp_nochange;
	player->psprites[ps_weapon].sy = WEAPONBOTTOM;

	P_SetPsprite( player, ps_weapon, newstate );
}

//
// P_CheckAmmo
// Returns true if there is enough ammo to shoot.
// If not, selects the next weapon to use.
//
qboolean P_CheckAmmo( player_t* player )
{
	ammotype_t		ammo;
	int			count;

	ammo = weaponinfo[player->readyweapon].ammo;

	// Minimal amount for one shot varies.
	if( player->readyweapon == wp_bfg )
	{
		count = BFGCELLS;
	}
	else if( player->readyweapon == wp_supershotgun )
	{
		count = 2;    // Double barrel.
	}
	else
	{
		count = 1;    // Regular.
	}

	// Some do not need ammunition anyway.
	// Return if current ammunition sufficient.
	if( ammo == am_noammo || player->ammo[ammo] >= count )
	{
		return true;
	}

	// Out of ammo, pick a weapon to change to.
	// Preferences are set here.
	do
	{
		if( player->weaponowned[wp_plasma]
				&& player->ammo[am_cell]
				&& ( ::g->gamemode != shareware ) )
		{
			player->pendingweapon = wp_plasma;
		}
		else if( player->weaponowned[wp_supershotgun]
				 && player->ammo[am_shell] > 2
				 && ( ::g->gamemode == commercial ) )
		{
			player->pendingweapon = wp_supershotgun;
		}
		else if( player->weaponowned[wp_chaingun]
				 && player->ammo[am_clip] )
		{
			player->pendingweapon = wp_chaingun;
		}
		else if( player->weaponowned[wp_shotgun]
				 && player->ammo[am_shell] )
		{
			player->pendingweapon = wp_shotgun;
		}
		else if( player->ammo[am_clip] )
		{
			player->pendingweapon = wp_pistol;
		}
		else if( player->weaponowned[wp_chainsaw] )
		{
			player->pendingweapon = wp_chainsaw;
		}
		else if( player->weaponowned[wp_missile]
				 && player->ammo[am_misl] )
		{
			player->pendingweapon = wp_missile;
		}
		else if( player->weaponowned[wp_bfg]
				 && player->ammo[am_cell] > 40
				 && ( ::g->gamemode != shareware ) )
		{
			player->pendingweapon = wp_bfg;
		}
		else
		{
			// If everything fails.
			player->pendingweapon = wp_fist;
		}

	}
	while( player->pendingweapon == wp_nochange );

	// Now set appropriate weapon overlay.
	P_SetPsprite( player,
				  ps_weapon,
				  ( statenum_t )( weaponinfo[player->readyweapon].downstate ) );

	return false;
}


//
// P_FireWeapon.
//
void P_FireWeapon( player_t* player )
{
	statenum_t	newstate;

	if( !P_CheckAmmo( player ) )
	{
		return;
	}

	P_SetMobjState( player->mo, S_PLAY_ATK1 );
	newstate = ( statenum_t )weaponinfo[player->readyweapon].atkstate;
	P_SetPsprite( player, ps_weapon, newstate );
	P_NoiseAlert( player->mo, player->mo );

	if( player->readyweapon == wp_chainsaw )
	{
		if( ::g->plyr == player )
		{
		}
	}

}



//
// P_DropWeapon
// Player died, so put the weapon away.
//
void P_DropWeapon( player_t* player )
{
	P_SetPsprite( player,
				  ps_weapon,
				  ( statenum_t )weaponinfo[player->readyweapon].downstate );
}



extern "C" {
//
// A_WeaponReady
// The player can fire the weapon
// or change to another weapon at this time.
// Follows after getting weapon up,
// or after previous attack/fire sequence.
//
	void
	A_WeaponReady
	( player_t*	player,
	  pspdef_t*	psp )
	{
		statenum_t	newstate;
		int		angle;

		// get out of attack state
		if( player->mo->state == &::g->states[S_PLAY_ATK1]
				|| player->mo->state == &::g->states[S_PLAY_ATK2] )
		{
			P_SetMobjState( player->mo, S_PLAY );
		}

		if( player->readyweapon == wp_chainsaw
				&& psp->state == &::g->states[S_SAW] )
		{
			if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
			{
				S_StartSound( player->mo, sfx_sawidl );
			}
		}

		// check for change
		//  if player is dead, put the weapon away
		if( player->pendingweapon != wp_nochange || !player->health )
		{
			// change weapon
			//  (pending weapon should allready be validated)
			newstate = ( statenum_t )weaponinfo[player->readyweapon].downstate;
			P_SetPsprite( player, ps_weapon, newstate );
			return;
		}

		// check for fire
		//  the missile launcher and bfg do not auto fire
		if( player->cmd.buttons & BT_ATTACK )
		{
			if( !player->attackdown
					|| ( player->readyweapon != wp_missile
						 && player->readyweapon != wp_bfg ) )
			{
				player->attackdown = true;
				P_FireWeapon( player );
				return;
			}
		}
		else
		{
			player->attackdown = false;
		}

		// bob the weapon based on movement speed
		angle = ( 128 *::g->leveltime )&FINEMASK;
		psp->sx = FRACUNIT + FixedMul( player->bob, finecosine[angle] );
		angle &= FINEANGLES / 2 - 1;
		psp->sy = WEAPONTOP + FixedMul( player->bob, finesine[angle] );
	}



//
// A_ReFire
// The player can re-fire the weapon
// without lowering it entirely.
//
	void A_ReFire
	( player_t*	player,
	  pspdef_t*	psp )
	{

		// check for fire
		//  (if a weaponchange is pending, let it go through instead)
		if( ( player->cmd.buttons & BT_ATTACK )
				&& player->pendingweapon == wp_nochange
				&& player->health )
		{
			player->refire++;
			P_FireWeapon( player );
		}
		else
		{
			player->refire = 0;
			P_CheckAmmo( player );
		}
	}


	void
	A_CheckReload
	( player_t*	player,
	  pspdef_t*	psp )
	{
		P_CheckAmmo( player );
#if 0
		if( player->ammo[am_shell] < 2 )
		{
			P_SetPsprite( player, ps_weapon, S_DSNR1 );
		}
#endif
	}



//
// A_Lower
// Lowers current weapon,
//  and changes weapon at bottom.
//
	void
	A_Lower
	( player_t*	player,
	  pspdef_t*	psp )
	{
		psp->sy += LOWERSPEED;

		// Is already down.
		if( psp->sy < WEAPONBOTTOM )
		{
			return;
		}

		// Player is dead.
		if( player->playerstate == PST_DEAD )
		{
			psp->sy = WEAPONBOTTOM;

			// don't bring weapon back up
			return;
		}

		// The old weapon has been lowered off the screen,
		// so change the weapon and start raising it
		if( !player->health )
		{
			// Player is dead, so keep the weapon off screen.
			P_SetPsprite( player,  ps_weapon, S_NULL );
			return;
		}

		player->readyweapon = player->pendingweapon;

		P_BringUpWeapon( player );
	}


//
// A_Raise
//
	void
	A_Raise
	( player_t*	player,
	  pspdef_t*	psp )
	{
		statenum_t	newstate;

		psp->sy -= RAISESPEED;

		if( psp->sy > WEAPONTOP )
		{
			return;
		}

		psp->sy = WEAPONTOP;

		// The weapon has been raised all the way,
		//  so change to the ready state.
		newstate = ( statenum_t )weaponinfo[player->readyweapon].readystate;

		P_SetPsprite( player, ps_weapon, newstate );
	}



//
// A_GunFlash
//
	void
	A_GunFlash
	( player_t*	player,
	  pspdef_t*	psp )
	{
		P_SetMobjState( player->mo, S_PLAY_ATK2 );
		P_SetPsprite( player, ps_flash, ( statenum_t )weaponinfo[player->readyweapon].flashstate );
	}



//
// WEAPON ATTACKS
//


//
// A_Punch
//
	void
	A_Punch
	( player_t*	player,
	  pspdef_t*	psp )
	{
		angle_t	angle;
		int		damage;
		int		slope;

		damage = ( P_Random() % 10 + 1 ) << 1;

		if( player->powers[pw_strength] )
		{
			damage *= 10;
		}

		angle = player->mo->angle;
		angle += ( P_Random() - P_Random() ) << 18;
		slope = P_AimLineAttack( player->mo, angle, MELEERANGE );
		P_LineAttack( player->mo, angle, MELEERANGE, slope, damage );

		// turn to face target
		if( ::g->linetarget )
		{
			S_StartSound( player->mo, sfx_punch );
			player->mo->angle = R_PointToAngle2( player->mo->x,
												 player->mo->y,
												 ::g->linetarget->x,
												 ::g->linetarget->y );
		}
	}


//
// A_Saw
//
	void
	A_Saw
	( player_t*	player,
	  pspdef_t*	psp )
	{
		angle_t	angle;
		int		damage;
		int		slope;

		damage = 2 * ( P_Random() % 10 + 1 );
		angle = player->mo->angle;
		angle += ( P_Random() - P_Random() ) << 18;

		// use meleerange + 1 se the puff doesn't skip the flash
		slope = P_AimLineAttack( player->mo, angle, MELEERANGE + 1 );
		P_LineAttack( player->mo, angle, MELEERANGE + 1, slope, damage );

		if( !::g->linetarget )
		{
			if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
			{
				S_StartSound( player->mo, sfx_sawful );
			}
			return;
		}
		if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
		{
			S_StartSound( player->mo, sfx_sawhit );
		}

		// turn to face target
		angle = R_PointToAngle2( player->mo->x, player->mo->y,
								 ::g->linetarget->x, ::g->linetarget->y );
		if( angle - player->mo->angle > ANG180 )
		{
			if( angle - player->mo->angle < UINT_MAX - ANG90 / 20 + 1 )	// SRS - make uint math explicit
			{
				player->mo->angle = angle + ANG90 / 21;
			}
			else
			{
				player->mo->angle -= ANG90 / 20;
			}
		}
		else
		{
			if( angle - player->mo->angle > ANG90 / 20 )
			{
				player->mo->angle = angle - ANG90 / 21;
			}
			else
			{
				player->mo->angle += ANG90 / 20;
			}
		}
		player->mo->flags |= MF_JUSTATTACKED;
	}



//
// A_FireMissile
//
	void
	A_FireMissile
	( player_t*	player,
	  pspdef_t*	psp )
	{
		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo]--;
		}
		P_SpawnPlayerMissile( player->mo, MT_ROCKET );

		if( ::g->plyr == player )
		{
		}

	}


//
// A_FireBFG
//
	void
	A_FireBFG
	( player_t*	player,
	  pspdef_t*	psp )
	{
		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS;
		}

		P_SpawnPlayerMissile( player->mo, MT_BFG );

		if( ::g->plyr == player )
		{
		}
	}



//
// A_FirePlasma
//
	void
	A_FirePlasma
	( player_t*	player,
	  pspdef_t*	psp )
	{
		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo]--;
		}

		P_SetPsprite( player,
					  ps_flash,
					  ( statenum_t )( weaponinfo[player->readyweapon].flashstate + ( P_Random() & 1 ) ) );

		P_SpawnPlayerMissile( player->mo, MT_PLASMA );

		if( ::g->plyr == player )
		{
		}
	}



//
// P_BulletSlope
// Sets a slope so a near miss is at aproximately
// the height of the intended target
//


	void P_BulletSlope( mobj_t*	mo )
	{
		angle_t	an;

		// see which target is to be aimed at
		an = mo->angle;
		::g->bulletslope = P_AimLineAttack( mo, an, 16 * 64 * FRACUNIT );

		if( !::g->linetarget )
		{
			an += 1 << 26;
			::g->bulletslope = P_AimLineAttack( mo, an, 16 * 64 * FRACUNIT );
			if( !::g->linetarget )
			{
				an -= 2 << 26;
				::g->bulletslope = P_AimLineAttack( mo, an, 16 * 64 * FRACUNIT );
			}
		}
	}


//
// P_GunShot
//
	void
	P_GunShot
	( mobj_t*	mo,
	  qboolean	accurate )
	{
		angle_t	angle;
		int		damage;

		damage = 5 * ( P_Random() % 3 + 1 );
		angle = mo->angle;

		if( !accurate )
		{
			angle += ( P_Random() - P_Random() ) << 18;
		}

		P_LineAttack( mo, angle, MISSILERANGE, ::g->bulletslope, damage );
	}


//
// A_FirePistol
//
	void
	A_FirePistol
	( player_t*	player,
	  pspdef_t*	psp )
	{
		if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
		{
			S_StartSound( player->mo, sfx_pistol );
		}

		P_SetMobjState( player->mo, S_PLAY_ATK2 );
		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo]--;
		}

		P_SetPsprite( player,
					  ps_flash,
					  ( statenum_t )weaponinfo[player->readyweapon].flashstate );

		P_BulletSlope( player->mo );
		P_GunShot( player->mo, !player->refire );

		if( ::g->plyr == player )
		{
		}
	}


//
// A_FireShotgun
//
	void
	A_FireShotgun
	( player_t*	player,
	  pspdef_t*	psp )
	{
		int		i;

		if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
		{
			S_StartSound( player->mo, sfx_shotgn );
		}
		P_SetMobjState( player->mo, S_PLAY_ATK2 );

		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo]--;
		}

		P_SetPsprite( player,
					  ps_flash,
					  ( statenum_t )weaponinfo[player->readyweapon].flashstate );

		P_BulletSlope( player->mo );

		for( i = 0 ; i < 7 ; i++ )
		{
			P_GunShot( player->mo, false );
		}

		if( ::g->plyr == player )
		{
		}
	}



//
// A_FireShotgun2
//
	void
	A_FireShotgun2
	( player_t*	player,
	  pspdef_t*	psp )
	{
		int		i;
		angle_t	angle;
		int		damage;


		if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
		{
			S_StartSound( player->mo, sfx_dshtgn );
		}
		P_SetMobjState( player->mo, S_PLAY_ATK2 );

		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo] -= 2;
		}

		P_SetPsprite( player,
					  ps_flash,
					  ( statenum_t )weaponinfo[player->readyweapon].flashstate );

		P_BulletSlope( player->mo );

		for( i = 0 ; i < 20 ; i++ )
		{
			damage = 5 * ( P_Random() % 3 + 1 );
			angle = player->mo->angle;
			angle += ( P_Random() - P_Random() ) << 19;
			P_LineAttack( player->mo,
						  angle,
						  MISSILERANGE,
						  ::g->bulletslope + ( ( P_Random() - P_Random() ) << 5 ), damage );
		}

		if( ::g->plyr == player )
		{
		}
	}


//
// A_FireCGun
//
	void
	A_FireCGun
	( player_t*	player,
	  pspdef_t*	psp )
	{
		if( globalNetworking || ( player == &::g->players[::g->consoleplayer] ) )
		{
			S_StartSound( player->mo, sfx_pistol );
		}

		if( !player->ammo[weaponinfo[player->readyweapon].ammo] )
		{
			return;
		}

		P_SetMobjState( player->mo, S_PLAY_ATK2 );
		if( ( player->cheats & CF_INFAMMO ) == false )
		{
			player->ammo[weaponinfo[player->readyweapon].ammo]--;
		}
		P_SetPsprite( player,
					  ps_flash,

					  ( statenum_t )(
						  weaponinfo[player->readyweapon].flashstate
						  + psp->state
						  - &::g->states[S_CHAIN1] ) );

		P_BulletSlope( player->mo );

		P_GunShot( player->mo, !player->refire );

		if( ::g->plyr == player )
		{
		}
	}



//
// ?
//
	void A_Light0( player_t* player, pspdef_t* psp )
	{
		player->extralight = 0;
	}

	void A_Light1( player_t* player, pspdef_t* psp )
	{
		player->extralight = 1;
	}

	void A_Light2( player_t* player, pspdef_t* psp )
	{
		player->extralight = 2;
	}


//
// A_BFGSpray
// Spawn a BFG explosion on every monster in view
//
	void A_BFGSpray( mobj_t* mo, void* )
	{
		int			i;
		int			j;
		int			damage;
		angle_t		an;

		// offset angles from its attack angle
		for( i = 0 ; i < 40 ; i++ )
		{
			an = mo->angle - ANG90 / 2 + ANG90 / 40 * i;

			// mo->target is the originator (player)
			//  of the missile
			P_AimLineAttack( mo->target, an, 16 * 64 * FRACUNIT );

			if( !::g->linetarget )
			{
				continue;
			}

			P_SpawnMobj( ::g->linetarget->x,
						 ::g->linetarget->y,
						 ::g->linetarget->z + ( ::g->linetarget->height >> 2 ),
						 MT_EXTRABFG );

			damage = 0;
			for( j = 0; j < 15; j++ )
			{
				damage += ( P_Random() & 7 ) + 1;
			}

			P_DamageMobj( ::g->linetarget, mo->target, mo->target, damage );
		}
	}


//
// A_BFGsound
//
	void
	A_BFGsound
	( player_t*	player,
	  pspdef_t*	psp )
	{
		S_StartSound( player->mo, sfx_bfg );
	}

}; // extern "C"


//
// P_SetupPsprites
// Called at start of level for each player.
//
void P_SetupPsprites( player_t* player )
{
	int	i;

	// remove all psprites
	for( i = 0 ; i < NUMPSPRITES ; i++ )
	{
		player->psprites[i].state = NULL;
	}

	// spawn the gun
	player->pendingweapon = player->readyweapon;
	P_BringUpWeapon( player );
}




//
// P_MovePsprites
// Called every tic by player thinking routine.
//
void P_MovePsprites( player_t* player )
{
	int		i;
	pspdef_t*	psp;
	const state_t*	state;

	psp = &player->psprites[0];
	for( i = 0 ; i < NUMPSPRITES ; i++, psp++ )
	{
		// a null state means not active
		if( ( state = psp->state ) )
		{
			// drop tic count and possibly change state

			// a -1 tic count never changes
			if( psp->tics != -1 )
			{
				psp->tics--;
				if( !psp->tics )
				{
					P_SetPsprite( player, i, psp->state->nextstate );
				}
			}
		}
	}

	player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
	player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
}

